﻿#pragma once

#include "nlohmann/json.hpp"
#include "resource.h"
#include <windows.h>

// 在没有测试的情况下，才编译包括那些 Windows API 的函数
// 使用GCC没有链接那些库的时候编译不了
#ifndef TESTING
int RestartAdmin() {
    // 管理员重启
    WCHAR path[MAX_PATH];
    GetModuleFileNameW(NULL, path, MAX_PATH); // 获取当前程序路径

    SHELLEXECUTEINFOW sei = {sizeof(sei)};
    sei.lpVerb = L"runas";     // 关键：请求提权
    sei.lpFile = path;         // 当前程序路径
    sei.nShow = SW_SHOWNORMAL; // 显示窗口

    if (ShellExecuteExW(&sei)) {
        exit(0);
    } else {
        return -1;
    }
}

HFONT SimpleFont(const wchar_t *fontName, int size, bool bold) {
    return CreateFont(size, 0, 0, 0, bold ? 700 : 400, FALSE, FALSE, FALSE,
                      DEFAULT_CHARSET, OUT_CHARACTER_PRECIS,
                      CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH,
                      fontName);
}

int DpiAware(double *iSc) {
    if (iSc != NULL)
        *iSc = 1;
    int rId = 0;
    HINSTANCE hLib = LoadLibrary(L"Shcore.dll");
    HINSTANCE hLib2 = LoadLibrary(L"user32.dll");
    if (hLib2 == NULL || hLib == NULL) {
        rId = 1;
    } else {
        typedef UINT(WINAPI * PFNDPI)(int);
        typedef UINT(WINAPI * PFNGET)();

        PFNDPI pfnDpi = (PFNDPI)GetProcAddress(hLib, "SetProcessDpiAwareness");
        if (pfnDpi != NULL) {
            pfnDpi(1);
        } else
            rId = 2;
        PFNGET pfnGet = (PFNGET)GetProcAddress(hLib2, "GetDpiForSystem");
        if (pfnGet != NULL) {
            int get = pfnGet();
            if (iSc != NULL)
                *iSc = get / 96.0;
        } else
            rId += 3;
        FreeLibrary(hLib);
        FreeLibrary(hLib2);
    }

    return rId;
}

int getWindowText_asInt(HWND hw, int *num) {
    wchar_t text[100] = {0};
    GetWindowTextW(hw, text, 100);
    int r = swscanf(text, L"%d", num);
    return r;
}

#endif

// 常量的定义
// 用户自定义消息
#define WM_CLICKDONE WM_USER
#define WM_GETKEY WM_USER + 1
#define WM_GET_MOUSE_POS WM_USER + 2

// 按钮
#define BUTTON_OPEN_KEY_DIALOG 1600
#define BUTTON_MORE_KEYS 1601
#define BUTTON_MOVE_TO 1606
#define BUTTON_MOUSE_LOCK 1604
#define EDIT_MOUSE_POS_X 1602
#define EDIT_MOUSE_POS_Y 1603
#define BUTTON_GET_MOUSE_POS 1605
#define GBOX_MOUSE 1700

// 热键
#define HOTKEY_CLICKING 1
#define HOTKEY_HIDE_WINDOW 2
#define HOTKEY_GET_MOUSE_POS 3

/*记忆文件包括：
持续点击，次数，间隔，虚拟键代码，
是否移动到指定位置（鼠标），是否锁定鼠标位置，鼠标位置(x,y)*/

nlohmann::json defMemo = {{"keep", false},
                          {"times", 100},
                          {"interval", 50},
                          {"vkey_id", -1},
                          {"move_to_pos", false},
                          {"lock_mouse", false},
                          {"mouse_pos", {{"x", 0}, {"y", 0}}}};

const int max_clickTimes = 100000; // 最大连点次数：10万次

/*配置文件包括：
管理员启动：没有管理员权限时提醒；总是尝试以管理员身份启动；不自动以管理员身份启动
记忆：程序启动时自动加载上一次的连点配置
警告：在锁定鼠标位置时警告
悬浮窗：连点时显示悬浮窗
自动隐藏：连点时自动隐藏主窗口
快捷键设置：3个快捷键
0-Ctrl;1-Shift;2-Alt
*/
const std::wstring adminActions[3] = { L"query",L"always",L"never" };
std::vector<int> defKey_clicking = {MOD_SHIFT, VK_F2};
std::vector<int> defKey_hideWindow = {MOD_CONTROL, 'Q'};
std::vector<int> defKey_getMousePos = {MOD_CONTROL, 'D'};
nlohmann::json defClickerConfig = {{"start_as_admin", "query"},
                                   {"load_memory", true},
                                   {"show_warnings", true},
                                   {"notice_window", true},
                                   {"hide_when_clicking", false},
                                   {"accelerators",
                                    {{"clicking", defKey_clicking},
                                     {"hide_window", defKey_hideWindow},
                                     {"get_mouse_pos", defKey_getMousePos}}}};